#include <linux/module.h>

#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include "led_opr.h"
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/gpio.h>

/*① 确定主设备号，也可以让内核分配*/
static int major = 0;
static struct class *button_class;
static int g_ledpins[100];
static int g_ledcnt = 0;




/*③ 实现对应的 drv_open/drv_read/drv_write 等函数，填入 file_operations 结构体*/
static ssize_t button_drv_read (struct file *file, char __user *buf, size_t size, loff_t * offset)
{
 	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);

	unsigned int minor = iminor(file_inode(file));
	char level;
	int err;
	
	level = p_led_opr->read(minor);
	err = copy_to_user(buf, &level, 1);
	return 1;

}

/* write(fd,&val,1) */
ssize_t button_drv_write (struct file *file,const char __user *buf, size_t size, loff_t * offset)
{
	int err;
	char states;
	struct inode *inode = file_inode(file);
	int minor = iminor(inode) ;
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	err = copy_from_user(&states, buf, 1);

	/* 获取应用程序传过来的次设备号和LED的状态值控制指定的LED */
	p_led_opr->ctl(minor,states);
	
	return 1;
}

static int button_drv_open (struct inode *node, struct file *file )
{
	int minor = iminor(node); 
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	
	/* open函数在这里可以用来初始化LED，怎么做呢？根据次设备号来初始化LED */
	p_led_opr->init(minor);
	
 	return 0;
}

static int button_drv_close (struct inode *node, struct file *file )
{
	
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	return 0;
}
/*③ 实现对应的 drv_open/drv_read/drv_write 等函数，填入 file_operations 结构体*/


/*② 定义自己的 file_operations 结构体*/
static  struct  file_operations button_drv={
	.owner     = THIS_MODULE,
	.read      = button_drv_read,
	.write     = button_drv_write,
	.open      = button_drv_open,
	.release   = button_drv_close,
	
};
/*② 定义自己的 file_operations 结构体*/




/*  platfrom driver begin-------------------------------------------*/

static int button_probe(struct platform_device *pdev)
{
    struct resource *res;
    int i = 1;
	
	major = register_chrdev(0, "button", &button_drv);  /* /dev/button */

   // while (1)
   // {
        res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
       // if (!res)
         //   break;
        
       // g_ledpins[g_ledcnt] = res->start;
		device_create(led_class, NULL, MKDEV(major, g_ledcnt), NULL, "button", minor); /* /dev/100ask_led0,1,... */
       // g_ledcnt++;
		
   // }
	
	button_class = class_create(THIS_MODULE, "button_class");
	err = PTR_ERR(button_class);
	if (IS_ERR(button_class)) {
		printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
		return -1;
    return 0;
    
}

static int button_remove(struct platform_device *pdev)
{
    struct resource *res;
    int i = 1;
	class_destroy(button_class);
   // while (1)
    {
        res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
       // if (!res)
        //    break;
		device_destroy(button_class, MKDEV(major, i));
        i++;
       // g_ledcnt--;
    }
	
	unregister_chrdev(major, "button");

	
    return 0;
}


static struct platform_driver button_driver = {
    .probe      = button_probe,
    .remove     = button_remove,
    .driver     = {
        .name   = "button_device_3_6",
    },
};

/*  platfrom driver end------------------------------------------------*/



/*  platfrom device begin--------------------------------------*/
static void button_device_release(struct device *dev)
{
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
}

static struct resource resources[] = {
        {
                .start = 1,
                .flags = IORESOURCE_IRQ,
                .name = "button_device_3_6_pin",
        },
        {

		},
};


static struct platform_device button_device = {
        .name = "button_device_3_6",
        .num_resources = ARRAY_SIZE(resources),
        .resource =resources,
        .dev = {
                .release = button_device_release,
         },
};
/*	platfrom device end --------------------------------------------*/





static int __init button_init(void)
{
    int err0,err1;
    
    err0 = platform_device_register(&button_device);
	err1 = platform_driver_register(&button_driver);
    
    return 0;
}

static void __exit button_exit(void)
{
    platform_device_unregister(&button_device);
	platform_driver_unregister(&button_driver);
}

module_init(button_init);
module_exit(button_exit);

MODULE_LICENSE("GPL");






